home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MacWorld 1999 July
/
Macworld (1999-07).dmg
/
Shareware World
/
Info
/
For Developers
/
Mops 3.4.sea
/
Mops source
/
Module source
/
pasmMod.txt
< prev
next >
Wrap
Text File
|
1998-12-28
|
35KB
|
1,454 lines
(* *********
\ PowerPC 601 Assembler
\ Copyright 1993-1994 Xan Gregg All Rights Reserved
\ Permission is granted for internal distribution by Creative Solutions, Inc.
\ Permission also granted for Mops distribution. Mops mods made by
\ Mike Hore.
This is a basic PowerPC 601 assembler. It uses a Forth-like syntax,
but the mnemonics and operand order is usually preserved. The exception
is the branching instructions, which will be seldom used anyway since
words like IF, and WHILE, are available. Often, duplicating identical
parameters is not required, such as if the source and destination
registers are the same.
Examples Motorola Syntax Forth Syntax
add. r1, r1, r2 r1 r2 add.,
cmpi cr1, r3, 25 cr1 r3 25 cmpi,
crnor crb1, crb1, crb4 crb1 crb4 crnor,
--ALSO-- cr0 bGT cr1 bLT crnor,
lfd fr1, 20(r2) fr1 20 r2 lfd,
mtspr MQ, r3 MQ r3 mtspr,
blt target target lt bc,
blt- target hint target lt bc,
bdnzl cr2, target cr2 target dnz bcl,
Non-PowerPC instructions are not included.
***** *)
decimal
\ First, the Mops version of the utility words, and a few
\ others we need as well:
PPC?
[IF]
: dbx postpone db ; immediate \ call the debugger - db is renamed!
[ELSE]
: dbx $ a9ff w, ; immediate
[THEN]
: DeferrErr true abort" DEFERRed word not set" ;
: DEFER ['] deferrErr vect ;
: IS postpone -> ; immediate
: TOKEN@ @abs ;
: TOKEN! reloc! ;
: TOKEN, reloc, ;
: NOT 0= ;
: SCALE ( val cnt -- val' )
dup 0< IF negate >> ELSE << THEN ;
: HEX# postpone $ ; immediate
: Lo2 $ 0000FFFF postpone literal postpone and ; immediate
: Hi2 $ FFFF0000 postpone literal postpone and ; immediate
: Hi2Lo 16 >> ;
: ERROR" postpone abort" ; immediate
: EVAL i >r evaluate r> -> i ; \ have to save & restore I till bug fixed
: OFF false swap ! ;
: ON true swap ! ;
: BLWORD Mword ;
: TOKEN.FOR state IF postpone ['] ELSE ' THEN ; immediate
: RANGE inline{ within?} ;
: SIMM? ( n -- n b ) \ is this a signed immediate (16 bit) value?
-32768 32767 within? ;
\ : UIMM? ( n -- n b )
\ 0 65535 within? ;
: PSTRCPY ( addr1\addr2 -- )
over c@ 1+ cmove ;
: HOLD$ \ ( addr len -- )
dup --> hld
hld swap cmove ;
: ALIGN4 \ pad with zero bytes till DP is 4-byte aligned
DP
4 reserve \ just to ensure pad bytes are zero
3 + $ fffffffc and -> DP ;
: #ALIGN4 \ ( n -- n' )
3 + $ fffffffc and ;
: code_align PPC?
IF CDP 4 erase CDP #align4 -> CDP
ELSE align4
THEN ;
\ defer codeHere ' here is codeHere
\ defer commaInstr ' , is commaInstr
: codeHere PPC? IF CDP ELSE DP THEN ;
\ note: code, (defined in Base) already looks at PPC? and does the right thing.
0 value opInstr \ instruction being assembled
\ : OR>INSTR ( n -- ) opInstr or -> opInstr ; \ experimenting:
: OR>INSTR ( n -- ) inline{ or> opInstr} ;
: ScaleOR>INSTR ( n\b -- ) scale or>instr ;
: >RaField ( n -- ) 16 scaleOr>Instr ;
: >RbField ( n -- ) 11 scaleOr>Instr ;
: >RcField ( n -- ) 6 scaleOr>Instr ;
: >RdField ( n -- ) 21 scaleOr>Instr ;
: >RsField ( n -- ) 21 scaleOr>Instr ;
: >LField ( n -- ) 21 scaleOr>Instr ;
: >TOField ( n -- ) 21 scaleOr>Instr ;
: >SRField ( n -- ) 16 scaleOr>Instr ;
: >SHField ( n -- ) 11 scaleOr>Instr ;
: >NBField ( n -- ) 11 scaleOr>Instr ;
: >MBField ( n -- ) 6 scaleOr>Instr ;
: >MEField ( n -- ) 1 scaleOr>Instr ;
: >DispField ( n -- ) Lo2 or>Instr ;
: >ImmField ( n -- ) Lo2 or>Instr ;
: >Imm5Field ( n -- ) Lo2 16 << or>Instr ;
hex# fa970000 constant RegisterID
hex# fa870000 constant FRegisterID
hex# fa770000 constant CRegisterID
hex# fa670000 constant CBRegisterID
hex# fa270000 constant VRegisterID
hex# fa570000 constant SPRegisterID
hex# fa470000 constant ModifierID
hex# fa370000 constant ConditionID
: MODIFIER ( value -- | create a register constant)
ModifierID or constant ;
: MODIFIER? ( [value] -- [value\true] | [false] )
depth 0 > IF dup Hi2 ModifierID = ELSE false THEN ;
: REGISTER ( value -- | create a register constant)
RegisterID or constant ;
: REGISTER# ( value -- n )
Lo2 ;
: REGISTER? ( [value] -- [value\true] | [false] )
depth 0 > IF dup Hi2 RegisterID = ELSE false THEN ;
: REGISTER#? ( [value] -- [value\true] | [false] )
register? dup if swap register# swap then ;
: NEEDREGISTER ( [value] -- )
register? not error" EXPECTED A REGISTER" ;
: NEEDREGISTER# ( [value] -- n )
register#? not error" EXPECTED A REGISTER" ;
: DECLAREREGISTERS ( -- )
32 0 DO
i 0 <# 2dup #s " register R" hold$ 2drop #s #> eval
LOOP ;
: FREGISTER ( value -- | create a register constant)
FRegisterID or constant ;
: FREGISTER? ( [value] -- [value\true] | [false] )
depth 0 > IF dup Hi2 FRegisterID = ELSE false THEN ;
: FREGISTER#? ( [value] -- [value\true] | [false] )
fregister? dup if swap register# swap then ;
: NEEDFREGISTER ( [value] -- )
fregister? not error" EXPECTED A FREGISTER" ;
: NEEDFREGISTER# ( [value] -- )
fregister#? not error" EXPECTED A FREGISTER" ;
: DECLAREFREGISTERS ( -- )
32 0 DO
i 0 <# 2dup #s " fregister FR" hold$ 2drop #s #> eval
LOOP
32 0 DO
i 0 <# 2dup #s " fregister F" hold$ 2drop #s #> eval
LOOP
;
: CREGISTER ( value -- | create a register constant)
CRegisterID or constant ;
: CREGISTER? ( [value] -- [value\true] | [false] )
depth 0 > IF dup Hi2 CRegisterID = ELSE false THEN ;
: CREGISTER#? ( [value] -- [value\true] | [false] )
cregister? dup if swap register# swap then ;
: NEEDCREGISTER ( [value] -- )
cregister? not error" EXPECTED A CREGISTER" ;
: DECLARECREGISTERS ( -- )
8 0 DO
i 0 <# 2dup #s " cregister CR" hold$ 2drop #s #> eval
LOOP ;
: CBREGISTER ( value -- | create a register constant)
CBRegisterID or constant ;
: CBREGISTER? ( [value] -- [value\true] | [false] )
depth 0 > IF dup Hi2 CBRegisterID = ELSE false THEN ;
: CBREGISTER#? ( [value] -- [value\true] | [false] )
cbregister? dup if swap register# swap then ;
: NEEDCBREGISTER ( [value] -- )
cbregister? not error" EXPECTED A CBREGISTER" ;
: DECLARECBREGISTERS ( -- )
32 0 DO
i 0 <# 2dup #s " cbregister CRB" hold$ 2drop #s #> eval
LOOP ;
: VREGISTER ( value -- | create a register constant)
VRegisterID or constant ;
: VREGISTER? ( [value] -- [value\true] | [false] )
depth 0 > IF dup Hi2 VRegisterID = ELSE false THEN ;
: VREGISTER#? ( [value] -- [value true] | [false] )
vregister? dup if swap register# swap then ;
: NEEDVREGISTER ( [value] -- )
vregister? not error" EXPECTED A VREGISTER" ;
: NEEDVREGISTER# ( [value] -- )
vregister#? not error" EXPECTED A VREGISTER" ;
: DECLAREVREGISTERS ( -- )
32 0 DO
i 0 <# 2dup #s " vregister V" hold$ 2drop #s #> eval
LOOP ;
: SPREGISTER ( value -- | create a register constant)
dup 31 and 5 scale swap -5 scale or SPRegisterID or constant ;
: SPREGISTER? ( [value] -- [value\true] | [false] )
depth 0 > IF dup Hi2 SPRegisterID = ELSE false THEN ;
: NEEDSPREGISTER ( [value] -- )
spregister? not error" EXPECTED An SPREGISTER" ;
: CONDITION ( value -- | create a condition constant)
conditionID or
constant ;
: CONDITION? ( [value] -- [value\true] | [false] )
depth 0 > IF dup Hi2 conditionID = ELSE false THEN ;
: NEEDCONDITION ( [value] -- )
condition? not error" EXPECTED A CONDITION" ;
: MODIFIERVALUE ( value -- n )
Lo2 ;
: CONDITIONVALUE ( value -- n )
Lo2 ;
\ branchHint is a one-shot set by 'hint' and cleared by the next branch instr.
variable branchHint
branchHint off
\ ASSEMBLER.WORDS
: hint branchHint on ;
DeclareRegisters
DeclareFRegisters
DeclareVRegisters
DeclareCRegisters
DeclareCBRegisters
0 SPRegister MQ
1 SPRegister XER
4 SPRegister RTCU
5 SPRegister RTCL
6 SPRegister DEC
8 SPRegister LR
9 SPRegister CTR
: bLT ( [cr] -- crb ) CRegister#? not IF 0 THEN 4* CBRegisterID or ;
: bGT ( [cr] -- crb ) CRegister#? not IF 0 THEN 4* 1+ CBRegisterID or ;
: bEQ ( [cr] -- crb ) CRegister#? not IF 0 THEN 4* 2+ CBRegisterID or ;
: bSO ( [cr] -- crb ) CRegister#? not IF 0 THEN 4* 3+ CBRegisterID or ;
create condArea 10 allot
: COND$ condArea count ;
: COND3 ( bit#\pos? -- )
blword condArea pstrcpy
IF hex# 180 ELSE hex# 080 THEN or
dup 0 <# cond$ hold$ " condition " hold$ #s #> eval
hex# f7f and
dup ( 1+) 0 <# cond$ hold$ " condition dnz" hold$ #s #> eval
hex# 040 or 0 <# cond$ hold$ " condition dz" hold$ #s #> eval
;
0 1 cond3 lt
1 1 cond3 gt
2 1 cond3 eq
3 1 cond3 so
4 1 cond3 un
0 0 cond3 nl
1 0 cond3 ng
2 0 cond3 ne
3 0 cond3 ns
4 0 cond3 nu
0 0 cond3 ge
1 0 cond3 le
hex# 200 condition dnz
hex# 240 condition dz
hex# 280 condition tr
1 modifier LONG \ for cmp instruction
0 modifier WD \ for cmp instruction ** note - can't use WORD
\ LOCAL.WORDS
\ GetDAB ( dreg [areg] [breg] tester -- | inserts D, A, and B regs into opInstr)
\ A and B are optional
: GetDAB ( d a b ) { tester \ d a b -- } \ inserts D, A, and B regs into opInstr)
tester execute not error" expected a register"
-> b
tester execute not IF \ 1 register: d,d,d
b -> a
a -> d
ELSE
-> a
tester execute IF \ 3 registers: d,a,b
-> d
ELSE \ 2 registers: d,d,a
a -> d
THEN
THEN
d >RdField a >RaField b >RbField ;
: GetDB ( d b ) { tester \ d b -- } \ inserts D and B regs into opInstr)
tester execute not error" expected a register"
-> b
tester execute not
IF \ 1 register: d,d
b -> d
ELSE
-> d
THEN
d >RdField b >RbField \ RaField stays zero
;
: GETRDAB ( dreg [areg] [breg] -- )
token.for register#? getDAB ;
: GETFRDAB ( dreg [areg] [breg] -- )
token.for fregister#? getDAB ;
: getCRBdab ( dreg [areg] [breg] -- )
token.for cbregister#? getDAB ;
: getVdab ( dreg [areg] [breg] -- )
token.for vregister#? getDAB ;
: getVdb ( dreg [areg] [breg] -- )
token.for vregister#? getDB ;
\ Checking words for immediates
: ?SIMM ( n -- )
simm? nip not error" EXPECTED A SIMM" ;
: ?UIMM ( n -- )
0 65535 range nip not error" EXPECTED A UIMM" ;
: ?UIMM5 ( n -- )
0 31 range nip not error" EXPECTED A 5-bit UIMM" ;
: ?UIMM4 ( n -- )
0 15 range nip not error" EXPECTED A 4-bit UIMM" ;
: ?SIMM5 ( n -- )
-16 15 range nip not error" EXPECTED A 5-bit UIMM" ;
\ GETDAIMM ( dreg [areg] simm tester -- | inserts D, and A regs and SIMM into opInstr)
\ A is optional
: GETDAIMM ( d [a] ) { simm tester \ d a -- }
simm tester execute
register#? not error" expected a register"
-> a
register#? not IF a THEN -> d
d >RdField a >RaField simm >ImmField
;
: getVdbUIMM5 ( d [b] ) { uimm5 \ d b -- }
uimm5 ?uimm5
getVdb
uimm5 >Imm5Field
;
: getVdSIMM5 ( d ) { simm5 \ d -- }
simm5 ?simm5
getVdb
simm5 >Imm5Field
;
: getVdabSH ( d [a] [b] ) { uimm4 \ d a b -- }
uimm4 ?uimm4
getVdab
uimm4 5 << or>Instr
;
: GETRDASIMM ( dreg\[areg]\simm -- )
token.for ?simm GetDAImm ;
: GETRDAUIMM ( dreg\[areg]\simm -- )
token.for ?uimm GetDAImm ;
: GETRDAIMM ( dreg [areg] imm -- )
token.for drop GetDAImm ;
\ GETDA ( dreg\[areg]\tester -- | inserts D and A regs into opInstr)
\ A is optional
\ 0 0 locals| d a tester |
: GETDA ( d [a] ) { tester \ d a -- }
tester execute not error" expected a register"
-> a
tester execute not IF a THEN -> d
d >RdField a >RaField ;
: GETRDA ( dreg [areg] -- )
token.for register#? GetDA ;
: GETRASBIMM ( [areg]\sreg\[breg]|[imm] -- )
register#? IF >RbField ELSE >ImmField THEN
needRegister# dup >R >RsField
register#? IF R> drop ELSE R> THEN >RaField ;
: GETRASB ( [areg]\sreg\breg -- )
needRegister# >RbField
needRegister# dup >R >RsField
register#? IF R> drop ELSE R> THEN >RaField ;
: GETRASIMM ( [areg]\sreg\imm -- )
dup ?uimm
>ImmField
needRegister# dup >R >RsField
register#? IF R> drop ELSE R> THEN >RaField ;
: GETCRLAB ( [crReg]\[L]\areg\breg -- )
needRegister# >RbField
needRegister# >RaField
modifier? IF ModifierValue >LField THEN
cregister#? if 23 ScaleOR>INSTR then ;
: (getCrLaImm)
>ImmField
needRegister# >RaField
modifier? IF ModifierValue >LField THEN
cregister#? if 23 ScaleOR>INSTR then ;
: GETCRLAIMM ( [crReg]\[L]\areg\imm -- )
dup ?simm (getCrLaImm) ;
: GETCRLAUIMM
dup ?uimm (getCrLaImm) ;
: GETCRFAB ( [crReg]\areg\breg -- )
needFRegister# >RbField
needFRegister# >RaField
cregister#? if 23 ScaleOR>INSTR then ;
: GETRAB ( areg\breg -- )
needRegister# >RbField
needRegister# >RaField ;
: GETRAS ( areg\[sreg] -- ) { \ s -- }
\ needRegister# locals| S |
needRegister# -> s
s >RsField
register#? not IF s THEN >RaField ;
: GETFRDB ( dfreg\[bfreg] -- ) { \ b -- }
\ needFRegister# locals| B |
needFRegister# -> b
b >RbField
fregister#? not IF b THEN >RdField ;
: GetNull ( -- )
;
: GetRsab ( [sreg]\areg\breg -- )
needRegister# >RbField
needRegister# dup >R >RaField
register#? IF R> drop ELSE R> THEN >RsField ;
: GetCRds ( CRd\CRs -- )
needCRegister register# 18 ScaleOR>INSTR
needCRegister register# 23 ScaleOR>INSTR ;
: GetCRd ( CRd -- )
needCRegister register# 23 ScaleOR>INSTR ;
: GetRd ( Rd -- )
needRegister# >RdField ;
: GetFRd ( dfreg -- )
needFRegister# >RdField ;
: GetRdSPR ( Rd\SPR -- )
needSPRegister register# 11 ScaleOR>INSTR
needRegister# >RdField ;
: GetRdSR ( Rd\SR -- )
>SRField
needRegister# >RdField ;
: GetRdb ( [Rd]\Rb -- )
needRegister# dup >R >RbField
register#? IF R> drop ELSE R> THEN >RdField ;
: getCRMRs ( CRM\Rs -- )
needRegister# >RsField
255 and 12 ScaleOR>INSTR ; \ bug fixed 25-Aug-94 via msg from xg
: getCRBd ( CRBd -- )
needCBRegister register# >RdField ;
: getFMFrb ( FM\FRb -- )
needFRegister# >RbField
255 and 17 ScaleOR>INSTR ;
: getCRdBImm ( CRd\Imm -- )
15 and 12 ScaleOR>INSTR
needCRegister register# 23 ScaleOR>INSTR ;
: GetRs ( sreg -- )
needRegister# >RsField ;
: GetSPRRs ( SPR\Rs -- )
needRegister# >RsField
needSPRegister register# 11 ScaleOR>INSTR ;
: getSRRs ( SR\Rs -- )
needRegister# >RsField
15 and >SRField ;
: getRsb ( [Rs]\Rb -- )
needRegister# dup >R >RbField
register#? IF R> drop ELSE R> THEN >RsField ;
: getRasSHMBME ( [Ra]\Rs\SH\MB\ME -- )
31 and >MEField
31 and >MBField
31 and >SHField
needRegister# dup >R >RsField
register#? IF R> drop ELSE R> THEN >RaField ;
: getRasbMBME ( [Ra]\Rs\Rb\MB\ME -- )
31 and >MEField
31 and >MBField
needRegister# >SHField
needRegister# dup >R >RsField
register#? IF R> drop ELSE R> THEN >RaField ;
: getRasSH ( [Ra]\Rs\SH -- )
31 and >SHField
needRegister# dup >R >RsField
register#? IF R> drop ELSE R> THEN >RaField ;
: getRsaDisp ( Rs\[disp\]Ra -- )
needRegister# >RaField
simm? if >DispField then
needRegister# >RsField ;
: getFRsRaDisp ( FRs\[disp\]Ra -- )
needRegister# >RaField
simm? if >DispField then
needFRegister# >RsField ;
: getFRsRab ( FRs\Ra\Rb -- )
needRegister# >RbField
needRegister# >RaField
needFRegister# >RsField ;
: getRsaNB ( [Ra]\Rs\NB -- )
31 and >NBField
needRegister# dup >R >RaField
register#? IF R> drop ELSE R> THEN >RsField ;
: getRb ( Rb -- )
needRegister# >RbField ;
: getVb ( Vb -- )
needVRegister# >RbField ;
: getVd ( Vd -- )
needVRegister# >RdField ;
: getTORab ( TO Ra Rb -- )
needRegister# >RbField
needRegister# >RaField
31 and >TOField ;
: getTORaSImm ( TO Ra Simm -- )
dup ?simm >ImmField
needRegister# >RaField
31 and >TOField ;
: getFRdRaDisp ( FRd [disp] Ra -- )
needRegister# >RaField
simm? if >DispField then
needFRegister# >RdField ;
: getFRdRab ( FRd Ra Rb -- )
needRegister# >RbField
needRegister# >RaField
needFRegister# >RdField ;
: getRdaDisp ( Rd [disp] Ra -- )
needRegister# >RaField
simm? if >DispField then
needRegister# >RdField ;
: getRdaNB ( Rd Ra nb -- )
31 and >NBField
needRegister# >RaField
needRegister# >RdField ;
: getFRdacb ( [FRd] FRa FRc FRb -- )
needFRegister# >RbField
needFRegister# >RcField
needFRegister# dup >R >RaField
fregister#? IF R> drop ELSE R> THEN >RdField ;
: getFRdac ( [FRd] FRa FRc -- )
needFRegister# >RcField
needFRegister# dup >R >RaField
fregister#? IF R> drop ELSE R> THEN >RdField ;
: getVdabc ( [VRd] VRa VRb VRc -- )
\ Note: vector mult and accumulate multiplies A and B then adds C,
\ whereas fmadd multiplies A and C then adds B, probably for historical
\ reasons (i.e. POWER). However in assembler we always put the
\ addition operand last.
needVRegister# >RcField
needVRegister# >RbField
needVRegister# dup >R >RaField
fregister#? IF R> drop ELSE R> THEN >RdField
;
: getabVd ( Vd a b ) { \ d a b -- }
\ a and b are GPRs, Vd is a VR - i.e. vector loads & stores. We
\ insist on all reg specifiers being present.
needRegister# >RbField
needRegister# >RaField
needVregister >RdField
;
: getVstrm { strm# -- }
strm# 21 scaleOr>Instr
;
: getabVstrm ( a b ) { strm# -- }
needRegister# >RbField
needRegister# >RaField
strm# getVstrm
;
: checkAddress ( addr\numBits -- addr )
over 3 and error" INVALID ADDRESS - NOT MULTIPLE OF 4"
1 swap 1- scale dup negate swap 1-
range not error" INVALID ADDRESS - OUT OF RANGE" ;
: ?hint \ set the branch bit if requested by the one-shot
branchHint @ if
branchHint off
1 21 scaleOr>Instr
then ;
: getAbsAddr
26 checkAddress
\ hex# 3FF,FFFC and or>Instr ?hint ;
hex# 3FFFFFC and or>Instr ?hint ;
: getRelAddr ( addr -- )
codehere - getAbsAddr ;
: getBOBI ( [crreg]\[cond] -- )
condition? IF
conditionValue 16 ScaleOr>Instr
ELSE
hex# 280 16 ScaleOr>Instr \ branch always if no condition
THEN
cregister#? IF
18 ScaleOr>Instr
THEN ?hint ;
: getUncondBOBI ( -- )
hex# 280 16 ScaleOr>Instr ; \ branch always
: getBOBIAddr ( addr\[cond]\[cond] -- )
condition? IF
conditionValue 16 ScaleOr>Instr
ELSE
hex# 280 16 ScaleOr>Instr \ branch always if no condition
THEN
opInstr 2 and not IF codehere - THEN
13 checkAddress hex# fffc and or>Instr
cregister#? IF
18 ScaleOr>Instr
THEN ?hint ;
\ -------------------------------------------------------
: OP ( primOp secOp -- ) \ main asm defining word
Mword find NIF cr ." Internal pasm error!" 1 die THEN
>r
<builds ( opcode1 opcode2 -- ) swap 26 scale or , r> token,
does> ( pfa -- | lays down instruction )
dup @ -> opInstr
4+ token@ execute
opInstr code, ;
: OP2 ( primOp secOp -- )
\ some Altivec instructions have the secondary opcode as listed
\ in the manual shifted left by one. It's easier to take care
\ of that here rather than change all the numbers and probably
\ introduce errors.
2* OP ;
create OPCODEArea 10 allot
: OPCODE$ opcodeArea count ;
create GETTERAREA 20 allot
: GETTER$ getterArea count ;
: DEFININGTEXT ( n1 n2 -- 0 | called from inside <# #> )
\ mh's note - we take care of converting the numbers to doubles here.
0 swap 0
opcode$ hold$ BL hold getter$ hold$ " OP " hold$ #S BL hold 2drop #s ;
\ : evaluate.string ( addr -- )
\ cr dup count type
\ evaluate.string
\ 40 >col here 14 .r ;
: OPo. ( opcode1 opcode2 -- super asm instruction defining word )
blword getterArea pstrcpy
blword opcodeArea pstrcpy
2* 2dup <# " ," hold$ definingText #> eval
2dup 1+ <# " .," hold$ definingText #> eval
2dup 1024 + <# " o," hold$ definingText #> eval
1025 + <# " o.," hold$ definingText #> eval
;
: OP. ( opcode1 opcode2 -- super asm instruction defining word )
blword getterArea pstrcpy
blword opcodeArea pstrcpy
2* 2dup <# " ," hold$ definingText #> eval
1+ <# " .," hold$ definingText #> eval
;
\ Vector ops with a dot, have the Rc bit in a different place
\ in the instruction (bit 21, not 31).
: OPv. ( opcode1 opcode2 -- super asm instruction defining word )
blword getterArea pstrcpy
blword opcodeArea pstrcpy
2dup <# " ," hold$ definingText #> eval
$ 400 or <# " .," hold$ definingText #> eval
;
\ ASSEMBLER.WORDS
31 266 OPo. getRdab add
31 10 OPo. getRdab addc
31 138 OPo. getRdab adde
14 0 OP getRdaSimm addi,
12 0 OP getRdaSimm addic,
13 0 OP getRdaSimm addic.,
15 0 OP getRdaSimm addis,
31 234 OPo. getRda addme
31 202 OPo. getRda addze
31 28 OP. getRasb and
31 60 OP. getRasb andc
28 0 OP getRasImm andi.,
29 0 OP getRasImm andis.,
( ** branch instructions ** )
18 0 OP getRelAddr b,
18 2 OP getAbsAddr ba,
18 1 OP getRelAddr bl,
18 3 OP getAbsAddr bla,
16 0 OP getBOBIAddr bc,
16 2 OP getBOBIAddr bca,
16 1 OP getBOBIAddr bcl,
16 3 OP getBOBIAddr bcla,
19 1056 OP getBOBI bcctr,
19 1057 OP getBOBI bcctrl,
19 32 OP getBOBI bclr,
19 33 OP getBOBI bclrl,
19 1056 OP getUncondBOBI bctr,
19 1057 OP getUncondBOBI bctrl,
19 32 OP getUncondBOBI blr,
19 33 OP getUncondBOBI blrl,
31 0 OP getCrLAB cmp,
11 0 OP getCrLAImm cmpi,
31 64 OP getCrLAB cmpl,
10 0 OP getCrLAUImm cmpli,
31 26 OP. getRas cntlzw
19 514 OP getCRBdab crand,
19 258 OP getCRBdab crandc,
19 578 OP getCRBdab creqv,
19 450 OP getCRBdab crnand,
19 66 OP getCRBdab crnor,
19 898 OP getCRBdab cror,
19 834 OP getCRBdab crorc,
19 386 OP getCRBdab crxor,
31 172 OP getRab dcbf,
31 940 OP getRab dcbi,
31 108 OP getRab dcbst,
31 556 OP getRab dcbt,
31 492 OP getRab dcbtst,
31 2028 OP getRab dcbz,
31 491 OPo. getRdab divw
31 459 OPo. getRdab divwu
31 620 OP getRdab eciwx,
31 876 OP getRdab ecowx,
31 1708 OP getNull eieio,
31 284 OP. getRasb eqv
31 954 OP. getRas extsb
31 922 OP. getRas extsh
63 264 OP. getFRdb fabs
63 21 OP. getFRdab fadd
59 21 OP. getFRdab fadds
63 64 OP getCRFab fcmpo,
63 0 OP getCRFab fcmpu,
63 14 OP. getFRdb fctiw
63 15 OP. getFRdb fctiwz
63 18 OP. getFRdab fdiv
59 18 OP. getFRdab fdivs
63 29 OP. getFRdacb fmadd
59 29 OP. getFRdacb fmadds
63 72 OP. getFRdb fmr
59 28 OP. getFRdacb fmsub
59 28 OP. getFRdacb fmsubs
63 25 OP. getFRdac fmul
59 25 OP. getFRdac fmuls
63 136 OP. getFRdb fnabs
63 40 OP. getFRdb fneg
63 31 OP. getFRdacb fnmadd
59 31 OP. getFRdacb fnmadds
63 30 OP. getFRdacb fnmsub
59 30 OP. getFRdacb fnmsubs
63 12 OP. getFRdb frsp
63 20 OP. getFRdab fsub
59 20 OP. getFRdab fsubs
31 1964 OP getRab icbi,
19 300 OP getNull isync,
34 0 OP getRdaDisp lbz,
35 0 OP getRdaDisp lbzu,
31 238 OP getRdab lbzux,
31 174 OP getRdab lbzx,
50 0 OP getFRdRaDisp lfd,
51 0 OP getFRdRaDisp lfdu,
31 1262 OP getFRdRab lfdux,
31 1198 OP getFRdRab lfdx,
48 0 OP getFRdRaDisp lfs,
49 0 OP getFRdRaDisp lfsu,
31 1134 OP getFRdRab lfsux,
31 1070 OP getFRdRab lfsx,
31 1198 OP getFRdRab lfdx,
42 0 OP getRdaDisp lha,
43 0 OP getRdaDisp lhau,
31 750 OP getRdab lhaux,
31 686 OP getRdab lhax,
31 1580 OP getRdab lhbrx,
40 0 OP getRdaDisp lhz,
41 0 OP getRdaDisp lhzu,
31 622 OP getRdab lhzux,
31 558 OP getRdab lhzx,
46 0 OP getRdaDisp lmw,
31 1194 OP getRdaNb lswi,
31 1066 OP getRdab lswx,
31 40 OP getRdab lwarx,
31 1068 OP getRdab lwbrx,
32 0 OP getRdaDisp lwz,
33 0 OP getRdaDisp lwzu,
31 110 OP getRdab lwzux,
31 46 OP getRdab lwzx,
19 0 OP getCRds mcrf,
63 128 OP getCRds mcrfs,
31 1024 OP getCRd mcrxr,
31 38 OP getRd mfcr,
\ 63 583 OP. getRd mffs
63 583 OP. getFRd mffs
31 166 OP getRd mfmsr,
31 678 OP getRdSPR mfspr,
31 1190 OP getRdSR mfsr,
31 1318 OP getRdb mfsrin,
31 288 OP getCRMRs mtcrf,
63 70 OP. getCRBd mtfsb0
63 38 OP. getCRBd mtfsb1
\ 31 711 OP. getFMFrb mtfsf
63 711 OP. getFMFrb mtfsf
63 134 OP. getCRdBImm mtfsfi
31 292 OP getRs mtmsr,
31 934 OP getSPRRs mtspr,
31 420 OP getSRRs mtsr,
31 484 OP getRsb mtsrin,
31 75 OP. getRdab mulhw
31 11 OP. getRdab mulhwu
31 235 OPo. getRdab mullw
7 0 OP getRdaSImm mulli,
31 476 OP. getRasb nand
31 104 OPo. getRda neg
31 124 OP. getRasb nor
31 444 OP. getRasb or
31 412 OP. getRasb orc
24 0 OP getRasImm ori,
25 0 OP getRasImm oris,
19 100 OP getNull rfi,
20 0 OP. getRasSHMBME rlwimi
21 0 OP. getRasSHMBME rlwinm
23 0 OP. getRasbMBME rlwnm
17 2 OP getNull sc,
31 24 OP. getRasb slw
\ 31 794OP. getRasb srad
31 792 OP. getRasb sraw
31 824 OP. getRasSH srawi
\ 31 539OP. getRasb srd
31 536 OP. getRasb srw
38 0 OP getRsaDisp stb,
39 0 OP getRsaDisp stbu,
31 494 OP getRsab stbux,
31 430 OP getRsab stbx,
54 0 OP getFRsRaDisp stfd,
55 0 OP getFRsRaDisp stfdu,
31 1518 OP getFRsRab stfdux,
31 1454 OP getFRsRab stfdx,
52 0 OP getFRsRaDisp stfs,
53 0 OP getFRsRaDisp stfsu,
31 1390 OP getFRsRab stfsux,
31 1326 OP getFRsRab stfsx,
44 0 OP getRsaDisp sth,
31 1836 OP getRsab sthbrx,
45 0 OP getRsaDisp sthu,
31 878 OP getRsab sthux,
31 814 OP getRsab sthx,
47 0 OP getRsaDisp stmw,
31 1450 OP getRsaNB stswi,
31 1322 OP getRsab stswx,
36 0 OP getRsaDisp stw,
31 1324 OP getRsab stwbrx,
31 301 OP getRsab stwcx.,
37 0 OP getRsaDisp stwu,
31 366 OP getRsab stwux,
31 302 OP getRsab stwx,
31 40 OPo. getRdab subf
31 8 OPo. getRdab subfc
31 136 OPo. getRdab subfe
08 0 OP getRdaSImm subfic,
31 232 OPo. getRda subfme
31 200 OPo. getRda subfze
31 1196 OP getNull sync,
31 612 OP getRb tlbie,
31 8 OP getTORab tw,
03 0 OP getTORaSImm twi,
31 316 OP. getRasb xor
26 0 OP getRasImm xori,
27 0 OP getRasImm xoris,
\ vector ops:
4 32 OP getVdabc vmhaddshs,
4 33 OP getVdabc vmhraddshs,
4 34 OP getVdabc vmladduhm,
4 36 OP getVdabc vmsumubm,
4 37 OP getVdabc vmsummbm,
4 38 OP getVdabc vmsumuhm,
4 39 OP getVdabc vmsumuhs,
4 40 OP getVdabc vmsumshm,
4 41 OP getVdabc vmsumshs,
4 42 OP getVdabc vsel,
4 43 OP getVdabc vperm,
4 44 OP getVdabSH vsldoi,
4 46 OP getVdab vmaddfp,
4 47 OP getVdabc vnmsubfp,
4 0 OP getVdab vaddubm,
4 64 OP getVdab vadduhm,
4 128 OP getVdab vadduwm,
4 384 OP getVdab vaddcuw,
4 512 OP getVdab vaddubs,
4 576 OP getVdab vadduhs,
4 640 OP getVdab vadduws,
4 768 OP getVdab vaddsbs,
4 832 OP getVdab vaddshs,
4 896 OP getVdab vaddsws,
4 1024 OP getVdab vsububm,
4 1088 OP getVdab vsubuhm,
4 1152 OP getVdab vsubuwm,
4 1408 OP getVdab vsubcuw,
4 1536 OP getVdab vsububs,
4 1600 OP getVdab vsubuhs,
4 1664 OP getVdab vsubuws,
4 1792 OP getVdab vsubsbs,
4 1856 OP getVdab vsubshs,
4 1920 OP getVdab vsubsws,
4 2 OP getVdab vmaxub,
4 66 OP getVdab vmaxuh,
4 130 OP getVdab vmaxuw,
4 258 OP getVdab vmaxsb,
4 322 OP getVdab vmaxsh,
4 386 OP getVdab vmaxsw,
4 514 OP getVdab vminub,
4 578 OP getVdab vminuh,
4 642 OP getVdab vminuw,
4 770 OP getVdab vminsb,
4 834 OP getVdab vminsh,
4 898 OP getVdab vminsw,
4 1026 OP getVdab vavgub,
4 1090 OP getVdab vavguh,
4 1154 OP getVdab vavguw,
4 1282 OP getVdab vavgsb,
4 1346 OP getVdab vavgsh,
4 1410 OP getVdab vavgsw,
4 4 OP getVdab vrlb,
4 68 OP getVdab vrlh,
4 132 OP getVdab vrlw,
4 260 OP getVdab vslb,
4 324 OP getVdab vslh,
4 388 OP getVdab vslw,
4 452 OP getVdab vsl,
4 516 OP getVdab vsrb,
4 580 OP getVdab vsrh,
4 644 OP getVdab vsrw,
4 708 OP getVdab vsr,
4 772 OP getVdab vsrab,
4 836 OP getVdab vsrah,
4 900 OP getVdab vsraw,
4 1028 OP getVdab vand,
4 1092 OP getVdab vandc,
4 1156 OP getVdab vor,
4 1220 OP getVdab vxor,
4 1284 OP getVdab vnor,
4 1540 OP getVd mfvscr,
4 1604 OP getVb mtvscr,
4 6 OPv. getVdab vcmpequb
4 70 OPv. getVdab vcmpequh
4 134 OPv. getVdab vcmpequw
4 198 OPv. getVdab vcmpequfp
4 454 OPv. getVdab vcmpgefp
4 518 OPv. getVdab vcmpgtub
4 582 OPv. getVdab vcmpgtuh
4 646 OPv. getVdab vcmpgtuw
4 710 OPv. getVdab vcmpgtfp
4 774 OPv. getVdab vcmpgtsb
4 838 OPv. getVdab vcmpgtsh
4 902 OPv. getVdab vcmpgtsw
4 966 OPv. getVdab vcmpbfp
4 8 OP getVdab vmuloub,
4 72 OP getVdab vmulouh,
4 264 OP getVdab vmulosb,
4 328 OP getVdab vmulosh,
4 520 OP getVdab vmuleub,
4 584 OP getVdab vmuleuh,
4 776 OP getVdab vmulesb,
4 840 OP getVdab vmulesh,
4 1544 OP getVdab vsum4ubs,
4 1800 OP getVdab vsum4sbs,
4 1608 OP getVdab vsum4shs,
4 1672 OP getVdab vsum2sws,
4 1928 OP getVdab vsumsws,
4 10 OP getVdab vaddfp,
4 74 OP getVdab vsubfp,
4 266 OP getVdb vrefp,
4 330 OP getVdb vsqrtefp,
4 394 OP getVdb vexptefp,
4 458 OP getVdb vlogefp,
4 522 OP getVdb vrfin,
4 586 OP getVdb vrfiz,
4 650 OP getVdb vrfip,
4 714 OP getVdb vrfim,
4 778 OP getVdbUIMM5 vcfux,
4 842 OP getVdbUIMM5 vcfsx,
4 906 OP getVdbUIMM5 vctusx,
4 970 OP getVdbUIMM5 vctsxs,
4 1034 OP getVdab vmaxfp,
4 1098 OP getVdab vminfp,
4 12 OP getVdab vmrghb,
4 76 OP getVdab vmrghh,
4 140 OP getVdab vmrghw,
4 268 OP getVdab vmrglb,
4 332 OP getVdab vmrglh,
4 396 OP getVdab vmrglw,
4 524 OP getVdbUIMM5 vspltb,
4 588 OP getVdbUIMM5 vsplth,
4 652 OP getVdbUIMM5 vspltw,
4 780 OP getVdSIMM5 vspltisb,
4 844 OP getVdSIMM5 vspltish,
4 908 OP getVdSIMM5 vspltisw,
4 1036 OP getVdab vslo,
4 1100 OP getVdab vsro,
4 14 OP getVdab vpkuhum,
4 78 OP getVdab vpkuwum,
4 142 OP getVdab vpkuhus,
4 206 OP getVdab vpkuwus,
4 270 OP getVdab vpkshus,
4 334 OP getVdab vpkswus,
4 398 OP getVdab vpkshss,
4 462 OP getVdab vpkswss,
4 526 OP getVdb vupkhsb,
4 590 OP getVdb vupkhsh,
4 654 OP getVdb vupklsb,
4 718 OP getVdb vupklsh,
4 782 OP getVdab vpkpx,
4 846 OP getVdb vupkhpx,
4 974 OP getVdb vupklpx,
\ vector data stream instructions:
31 342 OP2 getabVstrm dst,
31 342 $ 01000000 or OP2 getabVstrm dstt,
31 374 OP2 getabVstrm dstst,
31 $ 01000176 OP2 getabVstrm dststt,
31 822 OP2 getVstrm dss,
31 822 $ 01000000 or OP2 getVstrm dssall,
\ vector loads and stores:
31 6 OP2 getabVd lvsl,
31 7 OP2 getabVd lvebx,
31 39 OP2 getabVd lvehx,
31 71 OP2 getabVd lvewx,
31 103 OP2 getabVd lvx,
31 359 OP2 getabVd lvxl,
31 135 OP2 getabVd stvebx,
31 167 OP2 getabVd stvehx,
31 199 OP2 getabVd stvewx,
31 231 OP2 getabVd stvx,
31 487 OP2 getabVd stvxl,
\ Assembler Macro Definitions
\ Branching macros
: bcPatch ( instr addr\dest addr )
over - 13 checkAddress
hex# 0000FFFC and over @ hex# FFFF0003 and or swap ! ;
: bPatch ( instr addr\dest addr )
over - 24 checkAddress
hex# 03FFFFFC and over @ hex# FC000003 and or swap ! ;
: invertCondition ( condition -- condition' )
dup hex# 200 and 0= IF \ make sure it uses conditions
hex# 100 xor \ flip BO[1]
THEN ;
: if, ( condition -- addr\2 )
invertCondition codehere swap bc,
codehere 4- 2 ;
: else, ( addr\2 -- addr\3 )
2 ?pairs codehere 4+ bcPatch
codehere b,
codehere 4- 3 ;
: then, ( [addr\2] or [addr\3] -- )
dup 3 = IF
3 ?pairs codehere bpatch
ELSE
2 ?pairs codehere bcPatch
THEN ;
: begin, ( -- addr\1 )
codehere 1 ;
: while, ( condition -- addr\4 )
if, 2+ ;
: bcBackwhiles ( [addr\4]* -- )
begin
dup 4 =
while
drop codehere 4+ bcPatch
repeat ;
: again, ( addr\1[\addr\4]* -- )
bcBackwhiles
1 ?pairs
b, ;
: repeat, ( addr\1[\addr\4]* -- )
again, ;
: until, ( addr\1[\addr\4]*\condition -- )
>R bcBackwhiles
1 ?pairs
R> invertCondition bc, ;
\ these are simplified mnemonics from PowerPC manual
: nop, ( -- ) r0 r0 r0 or, ;
: li, ( rA\SIMM -- | load immediate ) r0 swap addi, ;
: lis, ( rA\SIMM -- | load immediate shifted ) r0 swap addis, ;
: lli, ( rA\SLIMM -- | load long immediate )
dup 0=
IF li,
ELSE
2dup extend dup \ rA\SLIMM\rA\simm\simm
IF li,
dup Hi2Lo swap hex# 8000 and IF \ sign bit set in lo 16 bits?
1+ Lo2
THEN
dup IF extend addis, ELSE 2drop THEN
ELSE \ lo half is 0
2drop Hi2Lo extend lis,
THEN
THEN ;
(* ***
old versions:
: li, ( rA\SIMM -- | load immediate ) r0 swap addi, ;
: lis, ( rA\SIMM -- | load immediate shifted ) r0 swap addis, ;
: lli, ( rA\SLIMM -- | load long immediate )
2dup extend li,
dup Hi2Lo swap hex# 8000 and IF \ sign bit set in lo 16 bits?
1+ Lo2
THEN
?dup IF extend addis, ELSE drop THEN ;
*** *)
: lui, ( rA SIMM -- | load immediate ) lli, ;
: la, ( rD SIMM\rA -- | load address ) swap addi, ;
: move, ( rA rS -- ) dup or, ;
: move., ( rA rS -- ) dup or., ;
: mr, ( rA rS -- ) dup or, ; \ "move reg" = same as move,
: mr., ( rA rS -- ) dup or., ;
: not, ( rA rS -- ) dup nor, ;
: not., ( rA rS -- ) dup nor., ;
: subi, ( rA SIMM -- ) negate addi, ;
: slwi, ( rA rS\n -- ) 0 over 31 swap - rlwinm, ;
\ : srwi, ( rA rS\n -- ) 32 over - swap 31 rlwimi, ; \ bug, I think
: srwi, ( rA rS\n -- ) 32 over - swap 31 rlwinm, ;
: mtlr, ( rA -- ) lr swap mtspr, ;
: mflr, ( rA -- ) lr mfspr, ;
: mtctr, ( rA -- ) ctr swap mtspr, ;
: mfctr, ( rA -- ) ctr mfspr, ;
: clr, ( rA -- ) dup dup subf, ;
\ Registers:
\ Important note: these definitions MUST MATCH those in ppc1!
: rOSSP r1 ; \ Operating system stack pointer
: rTOC r2 ; \ table of contents pointer
: rMainCode r13 ; \ base addr regs
: rMainData r14 ;
: rModCode r15 ;
: rModData r16 ;
: rRP r17 ; \ return stack pointer
: rSP r18 ; \ data stack pointer
: rFSP r19 ; \ floating stack pointer
: rObjBase r20 ; \ current object base addr
: rI r21 ; \ DO index
: rDo_limit r22 ; \ DO limit
\ Note: R11, R12, CR6, & CR7 are designated as scratch registers by Apple
\ : rX r11 ;
\ : rY r12 ;
\ : crX cr6 ;
\ : crY cr7 ;
\ r0 is also scratch but must be used carefully as it is special in some
\ instructions
\ Some Forth macros
\ dicaddr generates a dictionary address as offset, base-reg (as needed
\ for a load or store).
\ Usage:
\ r4 ' someWord dicaddr lwz,
: dicaddr { addr \ reg disp -- disp reg }
addr b&d -> disp -> reg
reg
CASE[ mainData_reg ]=> rMainData
[ modData_reg ]=> rModData
[ mainCode_reg ]=> rMainCode
[ modCode_reg ]=> rModCode
DEFAULT=>
]CASE
disp swap
;
\ dicaddr, generates a dictionary address in the designated register,
\ using addi . Note that it must be within 32k distance from where
\ the reg points, or we're out of luck.
\ Usage:
\ r4 ' someWord 2+ dicaddr,
: dicaddr, ( addr -- )
dicaddr swap addi,
;
: tst, ( reg -- ) 0 cmpi, ;
: rts, ( -- ) bclr, ;
decimal
false value pasm_done?
: FIND_IN_PASM \ ( s255 -- cfa true | -- s255 false )
find: pasmMod ;
: ENTERCODE \ begin assembly outside of a colon definition
lock: pasmMod
['] find_in_pasm -> extraFind \ look up words in pasm first. Exclude
\ locals and class stuff for the duration
false -> pasm_done?
code_align
;
\ :PPC_CODE begins a code definition. We set up a header specifying
\ no named parms/locals and 2 results. This means that the top 2 stack
\ cells will be in r4 and r3 on both entry and exit, which keeps things
\ simple.
: :PPC_CODE
ppc_header
$ BE00 codeW, \ handler code for PPC colon defns
$ 4200 codeW, \ non-leaf, modifies ctr (must be conservative),
\ no named parms/locals, 2 results
entercode
BEGIN
topfile -> source-ID (Frefill) IF interpret THEN
pasm_done?
UNTIL ;
: ;PPC_CODE
0 -> extraFind
unlock: pasmMod
true -> pasm_done?
?exec reveal
;
\ ppc? not
\ [IF]
// disAsm
\ [THEN]
: rX r11 ;
: rY r12 ;
: crX cr6 ;
: crY cr7 ;